﻿// -------------------------------------------------------------------------
//    @FileName         :    NFCacheDataMgr.h.h
//    @Author           :    Gao.Yi
//    @Date             :    2025-08-11
//    @Email			:    445267987@qq.com
//    @Module           :    NFCacheDataMgr.h
//    @Desc             :    缓存数据管理器声明
//                           提供缓存对象的获取、创建、续期、淘汰、批量加载等统一管理能力
//                           支持基于访问续期和创建兜底超时的双重过期机制
//
// -------------------------------------------------------------------------

#pragma once

#include "NFComm/NFObjCommon/NFObject.h"
#include "NFServerTypeDefine.h"

/**
 * @file NFCacheDataMgr.h
 * @brief 缓存数据管理器声明
 *
 * 提供缓存对象的获取、创建、续期、淘汰、批量加载等统一管理能力。
 */

class NFCacheData;

/**
 * @class NFCacheDataMgr
 * @brief 缓存数据管理器（共享内存对象）
 *
 * 职责：
 * - 通过对象类型与ID获取/创建缓存对象
 * - 基于访问续期与创建兜底超时进行有效性判断
 * - 在高负载时按比例扫描并移除过期对象
 * - 统一的批量加载入口，通过事务异步拉取数据
 *
 * 核心功能：
 * 1. 缓存对象生命周期管理
 *    - 创建新缓存对象
 *    - 获取现有缓存对象
 *    - 访问续期机制（滑动过期）
 *    - 创建兜底超时机制
 *
 * 2. 内存管理
 *    - 高负载时的自动淘汰
 *    - 轮询扫描过期对象
 *    - 内存使用率监控
 *
 * 3. 批量操作
 *    - 批量加载缓存数据
 *    - 过滤已有效的ID
 *    - 异步事务处理
 *
 * 设计特点：
 * - 支持双重过期机制（访问续期 + 创建兜底）
 * - 智能的内存管理和淘汰策略
 * - 高效的批量操作支持
 * - 完整的错误处理和日志记录
 */
class NFCacheDataMgr : public NF_OBJECT_GLOBAL_TEMPLATE_MACRO(NFCacheDataMgr, EOT_CACHE_DATA_OBJ_MGR, NFObject)
public:
    /**
     * @brief 构造函数，根据共享内存模式进行初始化
     * 
     * 根据共享内存管理器的创建模式选择初始化方式：
     * - EN_OBJ_MODE_INIT：冷启动模式，调用 CreateInit() 进行完整初始化
     * - 其他模式：热启动模式，调用 ResumeInit() 进行恢复初始化
     */
    NFCacheDataMgr();

    /**
     * @brief 析构函数
     * 
     * 清理资源，由于使用共享内存管理，通常无需特殊处理
     */
    ~NFCacheDataMgr() override;

    /**
     * @brief 冷启动创建初始化
     * 
     * 在共享内存冷启动场景下，对新创建的管理器对象进行初始化
     * 
     * @return 0 表示成功
     */
    int CreateInit();

    /**
     * @brief 热启动恢复初始化
     * 
     * 在共享内存热启动场景下，从持久化数据恢复管理器状态时调用
     * 
     * @return 0 表示成功
     */
    int ResumeInit();

public:
    /**
     * @brief 按类型与ID获取缓存对象（不续期）
     *
     * 该方法根据对象类型和唯一ID获取缓存对象。
     * 不会改变对象的过期时间，适用于只读访问场景。
     *
     * @param objType 缓存对象的类型
     * @param ullId   缓存对象的唯一标识ID
     * @return 指向缓存对象的指针，若未找到则返回 nullptr
     */
    virtual NFCacheData* GetCacheData(int objType, uint64_t ullId);

    /**
     * @brief 添加或覆盖缓存对象
     *
     * 该方法用于添加新的缓存对象或覆盖已有对象。
     * 如果对象已存在，则会续期并写入新数据。
     * 如果高负载，会触发扫描淘汰过期对象。
     *
     * @param objType   缓存对象的类型
     * @param pMessage  指向 Protobuf 消息对象的指针，用于初始化缓存对象
     * @return 指向缓存对象的指针，若失败则返回 nullptr
     */
    virtual NFCacheData* AddCacheData(int objType, const google::protobuf::Message* pMessage);

    /**
     * @brief 获取对象并进行访问续期（滑动过期）
     *
     * 该方法根据对象类型和唯一ID获取缓存对象，并更新其过期时间。
     * 适用于读写访问场景，确保频繁访问的对象不会被过早淘汰。
     *
     * @param objType 缓存对象的类型
     * @param ullId   缓存对象的唯一标识ID
     * @return 指向缓存对象的指针，若未找到则返回 nullptr
     */
    virtual NFCacheData* GetCacheDataAndSetExpire(int objType, uint64_t ullId);

    /**
     * @brief 获取最近有效对象
     *
     * 该方法根据对象类型和唯一ID获取最近有效的缓存对象。
     * 如果创建兜底已超时，则返回空指针，即使访问续期时间未到。
     *
     * @param objType 缓存对象的类型
     * @param ullId   缓存对象的唯一标识ID
     * @return 指向缓存对象的指针，若未找到或超时则返回 nullptr
     */
    virtual NFCacheData* GetRecentCacheData(int objType, uint64_t ullId);

public:
    /**
     * @brief 获取缓存对象（模板版本，不续期）
     * 
     * 使用模板参数简化调用，自动推导对象类型：
     * 1. 通过模板参数获取具体的对象类型
     * 2. 调用非模板版本的获取方法
     * 3. 提供更简洁的API接口
     * 
     * @tparam cacheClass 具体的缓存数据类型
     * @param ullId       缓存对象的唯一标识ID
     * @return 指向缓存对象的指针，若未找到则返回 nullptr
     */
    template <typename cacheClass>
    NFCacheData* GetCacheData(uint64_t ullId)
    {
        return GetCacheData(cacheClass::GetStaticClassType(), ullId);
    }

    /**
     * @brief 添加缓存对象（模板版本）
     * 
     * 使用模板参数简化调用，自动推导对象类型：
     * 1. 通过模板参数获取具体的对象类型
     * 2. 调用非模板版本的添加方法
     * 3. 提供更简洁的API接口
     * 
     * @tparam cacheClass 具体的缓存数据类型
     * @param pMessage    指向 Protobuf 消息对象的指针
     * @return 指向缓存对象的指针，若失败则返回 nullptr
     */
    template <typename cacheClass>
    NFCacheData* AddCacheData(const google::protobuf::Message* pMessage)
    {
        return AddCacheData(cacheClass::GetStaticClassType(), pMessage);
    }

    /**
     * @brief 获取并续期对象（模板版本）
     * 
     * 使用模板参数简化调用，自动推导对象类型：
     * 1. 通过模板参数获取具体的对象类型
     * 2. 调用非模板版本的获取并续期方法
     * 3. 提供更简洁的API接口
     * 
     * @tparam cacheClass 具体的缓存数据类型
     * @param ullId       缓存对象的唯一标识ID
     * @return 指向缓存对象的指针，若未找到则返回 nullptr
     */
    template <typename cacheClass>
    NFCacheData* GetCacheDataAndSetExpire(uint64_t ullId)
    {
        return GetCacheDataAndSetExpire(cacheClass::GetStaticClassType(), ullId);
    }

    /**
     * @brief 获取最近有效对象（模板版本）
     * 
     * 使用模板参数简化调用，自动推导对象类型：
     * 1. 通过模板参数获取具体的对象类型
     * 2. 调用非模板版本的获取最近有效对象方法
     * 3. 提供更简洁的API接口
     * 
     * @tparam cacheClass 具体的缓存数据类型
     * @param ullId       缓存对象的唯一标识ID
     * @return 指向缓存对象的指针，若未找到或超时则返回 nullptr
     */
    template <typename cacheClass>
    NFCacheData* GetRecentCacheData(uint64_t ullId)
    {
        return GetRecentCacheData(cacheClass::GetStaticClassType(), ullId);
    }

public:
    /**
     * @brief 批量加载缓存数据
     * 
     * 批量加载缓存数据的完整流程：
     * 1. 遍历ID列表，过滤掉已经有效的缓存对象
     * 2. 如果所有ID都已有效，直接返回成功
     * 3. 创建批量获取事务，发起异步加载请求
     * 4. 事务完成后会自动将数据添加到缓存中
     * 
     * @param serverType        目标存储服务器类型
     * @param objType           缓存对象类型
     * @param getCacheTransType 获取事务类型（用于创建具体拉取事务）
     * @param loadCacheTransType 加载事务类型
     * @param iTableId          数据表ID
     * @param roleId            角色ID
     * @param vecId             需要拉取的ID列表
     * @param iReason           调用原因
     * @return 0 表示成功，其他值为错误码
     */
    virtual int BatchLoadCacheData(int serverType, int objType, int getCacheTransType, int loadCacheTransType, int iTableId, uint64_t roleId, const std::vector<uint64_t>& vecId, int iReason);

public:
    /**
     * @brief 移除指定的缓存对象
     *
     * 该方法用于从缓存中移除给定的缓存对象。
     * 会释放对象占用的内存空间，并记录相关日志。
     *
     * @param pCacheData 指向需要移除的缓存对象的指针
     * @return 0 表示成功，其他值为错误码
     */
    virtual int RemoveCacheData(NFCacheData* pCacheData);

    /**
     * @brief 扫描并移除过期对象
     * 
     * 使用轮询扫描的方式移除过期对象：
     * 1. 使用静态迭代器记录上次扫描位置，实现轮询扫描
     * 2. 检查每个对象的访问续期时间是否已过期
     * 3. 移除过期的对象，释放内存空间
     * 4. 返回实际移除的对象数量
     * 
     * @param objType   对象类型
     * @param iScanNum  本次扫描数量上限
     * @return 实际移除数量
     */
    virtual int RemoveExpiredCacheData(int objType, int iScanNum);

    /**
     * @brief 判断对象是否存在
     * 
     * 检查指定类型和ID的缓存对象是否存在。
     * 
     * @param objType 缓存对象的类型
     * @param ullId   缓存对象的唯一标识ID
     * @return true 表示存在，false 表示不存在
     */
    virtual bool IsExistCacheData(int objType, uint64_t ullId);
};
